/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.system.service.impl;

import me.zhengjie.modules.system.domain.Image;
import me.zhengjie.modules.system.domain.TaskMark;
import me.zhengjie.modules.system.domain.vo.MeritsVo;
import me.zhengjie.modules.system.service.dto.ImageDto;
import me.zhengjie.modules.system.service.dto.UserDto;
import me.zhengjie.utils.ValidationUtil;
import me.zhengjie.utils.FileUtil;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.system.repository.TaskMarkRepository;
import me.zhengjie.modules.system.service.TaskMarkService;
import me.zhengjie.modules.system.service.dto.TaskMarkDto;
import me.zhengjie.modules.system.service.dto.TaskMarkQueryCriteria;
import me.zhengjie.modules.system.service.mapstruct.TaskMarkMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;

import java.sql.Time;
import java.sql.Timestamp;
import java.util.*;
import java.io.IOException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author whj
* @date 2021-01-16
**/
@Service
@RequiredArgsConstructor
public class TaskMarkServiceImpl implements TaskMarkService {

    private final TaskMarkRepository taskMarkRepository;
    private final TaskMarkMapper taskMarkMapper;

    @Override
    public Map<String,Object> queryAll(TaskMarkQueryCriteria criteria, Pageable pageable){
        Page<TaskMark> page = taskMarkRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(taskMarkMapper::toDto));
    }

    @Override
    public List<TaskMarkDto> queryAll(TaskMarkQueryCriteria criteria){
        return taskMarkMapper.toDto(taskMarkRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public TaskMarkDto findById(Integer id) {
        TaskMark taskMark = taskMarkRepository.findById(id).orElseGet(TaskMark::new);
        ValidationUtil.isNull(taskMark.getMarkTaskId(),"TaskMark","id",id);
        return taskMarkMapper.toDto(taskMark);
    }

    @Override
    // 一个MeritsVo代表一个日期的绩效
    public List<MeritsVo> queryMerits(TaskMarkQueryCriteria criteria) {
        Timestamp timeStart = criteria.getUploadJsonTime().get(0);
        Timestamp timeEnd = criteria.getUploadJsonTime().get(1);
        Timestamp timeStep =new Timestamp(timeStart.getTime()+(long)(1000*3600*24-1000*1.01));   //每步一天
        List<MeritsVo> meritsVos = new ArrayList<>();
        for (; timeStep.before(timeEnd);){      // 从开始日期到结束，每次遍历一天
            List<Timestamp> timestamp = new ArrayList<>();
            timestamp.add(timeStart);
            timestamp.add(timeStep);
            criteria.setUploadJsonTime(timestamp);
            List<TaskMarkDto> taskMarkDtos = taskMarkMapper.toDto((taskMarkRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))));
            //去重
            Set<TaskMarkDto> personSet = new TreeSet<>((o1, o2) -> o1.getMarkTaskId().compareTo(o2.getMarkTaskId()));
            personSet.addAll(taskMarkDtos);
            taskMarkDtos = new ArrayList<>(personSet);      //  每天的任务列表
            //如果无任务，continue
            if (taskMarkDtos.size()==0) {
                timeStep = new Timestamp(timeStep.getTime()+(long)1000*3600*24);
                timeStart = new Timestamp(timeStart.getTime()+(long)1000*3600*24);
                continue;
            }
            //如果有任务
            MeritsVo meritsVo = new MeritsVo();     //当前时间的绩效，一个循环加一个
            meritsVo.setImageBox(Long.valueOf(0));
            meritsVo.setImageNum(Long.valueOf(0));
            List<ImageDto> imageDtos = new ArrayList<>();   //符合当前时间范围的的图片
            //查询当前任务，此时taskMarkDtos只有一个
            if (criteria.getIsAllMerits() == 0){
                List<ImageDto> currentImageDtos = taskMarkDtos.get(0).getImages();
                meritsVo.setTaskName(taskMarkDtos.get(0).getTaskName());
                for (int i =currentImageDtos.size()-1; i >=0; i--) {
                    if(currentImageDtos.get(i).getUploadJsonTime() == null) continue;
                    // 若UploadJsonTime不在时间范围内则移除
                    if (!currentImageDtos.get(i).getUploadJsonTime().before(timeStep)||!currentImageDtos.get(i).getUploadJsonTime().after(timeStart)){
                        currentImageDtos.remove(i);
                    }
                }
                imageDtos=currentImageDtos;
            }else {                 //查询所有任务，此时taskMarkDto里有多个
                for (TaskMarkDto item:taskMarkDtos) {
                    if (meritsVo.getTaskName().contains(item.getTaskName())!=true) meritsVo.setTaskName(item.getTaskName()+";"+meritsVo.getTaskName());
                    List<ImageDto> allImageDtos = item.getImages();
                    for (int i =allImageDtos.size()-1; i >=0; i--) {
                        if(allImageDtos.get(i).getUploadJsonTime() == null) continue;
                        if (!allImageDtos.get(i).getUploadJsonTime().before(timeStep)||!allImageDtos.get(i).getUploadJsonTime().after(timeStart)){
                            allImageDtos.remove(i);
                        }
                    }
                    imageDtos.addAll(allImageDtos);
                }
            }
            meritsVo.setImageDtos(imageDtos);
            for (ImageDto item:imageDtos) {
                meritsVo.setDate(timeStart.toString().substring(0,10)); //时间只保留到天
                //若图片是等待审核或审核通过，则更新当天绩效
                if (item.getStatus()==3||item.getStatus()==4){
                    meritsVo.setImageNum(meritsVo.getImageNum()+1);
                    meritsVo.setImageBox(meritsVo.getImageBox()+item.getNumBox());
                }
            }
            meritsVos.add(meritsVo);
            //调整时间区间
            timeStep = new Timestamp(timeStep.getTime()+(long)1000*3600*24);
            timeStart = new Timestamp(timeStart.getTime()+(long)1000*3600*24);
        }
        return meritsVos;
    }

    @Override
    public UserDto queryTaskMember(Integer markTaskId) {
        Optional<TaskMark> taskMark = taskMarkRepository.findById(markTaskId);
        TaskMarkDto taskMarkDto = taskMarkMapper.toDto(taskMark.get());
        return taskMarkDto.getUsers().get(0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskMarkDto create(TaskMark resources) {
        return taskMarkMapper.toDto(taskMarkRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(TaskMark resources) {
        TaskMark taskMark = taskMarkRepository.findById(resources.getMarkTaskId()).orElseGet(TaskMark::new);
        ValidationUtil.isNull( taskMark.getMarkTaskId(),"TaskMark","id",resources.getMarkTaskId());
        taskMark.copy(resources);
        taskMarkRepository.save(taskMark);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            taskMarkRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<TaskMarkDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (TaskMarkDto taskMark : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("任务名", taskMark.getTaskName());
            map.put("分配到的文件路径", taskMark.getFileList());
            map.put("file_list中所含有的图片数量", taskMark.getNumImage());
            map.put("已完成的图片数量", taskMark.getNumFinish());
            map.put("创建任务的时间", taskMark.getCreateTime());
            map.put("完成时间", taskMark.getFinishTime());
            map.put("已审核通过的图片数量", taskMark.getNumChecked());
            map.put("0未完成/1完成部分/2等待审核/3审核通过/4审核不通过", taskMark.getStatus());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}